/*
 * Created by SharpDevelop.
 * User: ksswyer
 * Date: 7/10/2006
 * Time: 9:46 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace GPSSatellite.Components
{
	/// <summary>
	/// Description of UserControl1.
	/// </summary>
	public partial class c_SatelliteSignalBars
	{
		private const ushort MAXBARS 		= 12;
		private const uint	 MAXSCALE 		= 10000;
		private const string CategoryName 	= "Satellite Signal Bars";
	
		private Image mDobleBack = null;
		private string[] mSatName = new string[MAXBARS];
		private ESatStatus[]	mSatStauts = new ESatStatus[MAXBARS];
		
		#region Component Settings Members
		private ushort	mNumberBars = 3;
		private bool	mMultiColor = true;
		private bool	mShowLabels = true;
		private uint	mScaleMax	= 100;
		private ushort	mBarSpacing = 5;
		#endregion
		
		
		
		private Color[]	mSatColors = {
			Color.Purple,
			Color.LightSteelBlue,
			Color.ForestGreen,
			Color.Aquamarine,
			Color.Orange,
			Color.Yellow,
			Color.Red,
			Color.Plum,
			Color.CornflowerBlue,
			Color.Blue,
			Color.Olive,
			Color.BurlyWood
		};
		
		private enum ESatStatus: byte {	NOSAT=0,
										BELOW_NOFILL=4,
										BELOW_FILL=5,
										BELOW_FILLD=7,
										ABOVE_NOFILL=20,
										ABOVE_FILL=21,
										ABOVE_FILLD=23};
		public c_SatelliteSignalBars()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
						
			//mSatColors = new Color[MAXBARS];
			
		}
		
		
		public void SetSatSignal(int sat, uint signal, string text,byte status){
			if ((mSatRect !=null)&&(sat <= mSatRect.Length)){
				if (signal > mScaleMax) signal = mScaleMax;
				int oldheight = mSatRect[sat-1].Height;
				double step = satheight/mScaleMax;
				step *= signal;
				mSatRect[sat-1].Height =(int)step;// ((int)(satheight/(int)mScaleMax))*(int)signal;
				//also, we draw top down, so we have to recal the Y coord
				mSatRect[sat-1].Y += oldheight-mSatRect[sat-1].Height;
				mSatName[sat-1] = text;
				mSatStauts[sat-1] = (ESatStatus)status;
				this.Invalidate();
			}
		}
		#region Component Settings
		
		[Category(CategoryName)]
		[Description("Number of satellite bars.")]
		public ushort NumberSatBars
		{
			get { return mNumberBars; }
			set
			{
				if (mNumberBars> MAXBARS)
					mNumberBars = MAXBARS;
				else
					mNumberBars = value;
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Use colored bars = true or single color bars=false.")]
		public bool Multicolored
		{
			get { return mMultiColor; }
			set
			{
				mMultiColor = value;
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Show labels under each bar=true, no labels = false.")]
		public bool ShowLabels
		{
			get { return mShowLabels; }
			set
			{
				mShowLabels = value;
				InvalidateBuffer(true);
			}
		}
		[Category(CategoryName)]
		[Description("Upper limit of the scale for displaying. Min is always 0.")]
		public uint MaxScale
		{
			get { return mScaleMax; }
			set
			{
				if (mScaleMax > MAXSCALE)
					mScaleMax=MAXSCALE;
				else
					mScaleMax = value;
				InvalidateBuffer(true);
			}
		}
		#endregion
		
		#region Draw Methods
		private void DisposeBrushes()
		{
			if (mBrush != null)
			{
				mBrush.Dispose();
				mBrush = null;
			}

		}
		private void InvalidateBuffer()
		{
			InvalidateBuffer(false);
		}

		private void InvalidateBuffer(bool InvalidateControl)
		{
			if (mDobleBack != null)
			{
				mDobleBack.Dispose();
				mDobleBack = null;
			}

			if (InvalidateControl)
			{
				this.Invalidate();
			}
		}
		private void DrawString(Graphics gfx, Rectangle box,string text)
		{
			SizeF ss = gfx.MeasureString(text, this.Font);

			float left = box.X + (box.Width - ss.Width)/2;
			float top = box.Y + (box.Height - ss.Height)/2;

			
			SolidBrush mTextBrush = new SolidBrush(Color.Black);
			gfx.DrawString(text, this.Font, mTextBrush, left, top);
			mTextBrush.Dispose();

		}
		#endregion
		
		#region CreatePaintElements

		private Rectangle[] mSatRect = null;
		private Pen mPenIn = new Pen(Color.Black,2);
		private Brush	mBrush;
		private int satheight = 0;
		private int satwidth = 0;
		
		private void CreatePaintElements()
		{
			DisposeBrushes();
			mSatRect = new Rectangle[this.mNumberBars];
			mBrush = new SolidBrush(Color.Red);
			
			int hspacing = (this.mNumberBars+1)*mBarSpacing;
			int vspacing = 4;
			if (this.mShowLabels)
				vspacing = 25;
			
			//determine each bar size
			satwidth = (int)((this.Width - hspacing)/this.mNumberBars);
			satheight = (int)((this.Height - vspacing));
			
			for (int i=0; i<this.mNumberBars;i++){
				//create the rects for the sat bars
				mSatRect[i] = new Rectangle(
				                this.ClientRectangle.X+((satwidth*i)+(mBarSpacing*(i+1))),
				        		this.ClientRectangle.Y+2,
				        		satwidth,
				        		satheight);
				                            	
			}
			
		}

		#endregion
		#region OnPaint

		protected override void OnPaint(PaintEventArgs e)
		{
			//System.Diagnostics.Debug.WriteLine("Paint " + this.Name + "  Pos: "+this.Position.ToString());
			if (!this.IsDisposed)
			{
				
				if (mDobleBack == null)
				{
					
					mDobleBack = new Bitmap(this.Width, this.Height);
					CreatePaintElements();
			
				}

				Image ima = new Bitmap(mDobleBack);

				Graphics gtemp = Graphics.FromImage(ima);

				for (int i=0; i<this.mNumberBars;i++){
						Brush	brush = new SolidBrush(mSatColors[i]);
						//create the rects for the sat bars
						//NOTE: could make this smaller when i figure out the status
						//100%
						switch (mSatStauts[i]){
							case ESatStatus.ABOVE_NOFILL:
								gtemp.DrawRectangle(new Pen(mSatColors[i],2),mSatRect[i]);
								break;
							case ESatStatus.BELOW_NOFILL:
								gtemp.DrawRectangle(new Pen(mSatColors[i],2),mSatRect[i]);
								break;
							case ESatStatus.ABOVE_FILL:
								gtemp.FillRectangle(brush, mSatRect[i]);
								gtemp.DrawRectangle(mPenIn,mSatRect[i]);
								break;
							case ESatStatus.BELOW_FILL:
								gtemp.FillRectangle(brush, mSatRect[i]);
								gtemp.DrawRectangle(mPenIn,mSatRect[i]);
								break;
							case ESatStatus.ABOVE_FILLD:
								gtemp.FillRectangle(brush, mSatRect[i]);
								gtemp.DrawRectangle(mPenIn,mSatRect[i]);
								DrawString(gtemp,new Rectangle(mSatRect[i].X,mSatRect[i].Y-20,mSatRect[i].Width,20),"D");
								break;
								
							case ESatStatus.BELOW_FILLD:
								gtemp.FillRectangle(brush, mSatRect[i]);
								gtemp.DrawRectangle(mPenIn,mSatRect[i]);
								DrawString(gtemp,new Rectangle(mSatRect[i].X,mSatRect[i].Y-20,mSatRect[i].Width,20),"D");
								break;
						}
						
						DrawString(gtemp,new Rectangle(mSatRect[i].X,this.Height-20,mSatRect[i].Width,20),mSatName[i]);
					};
				
				e.Graphics.DrawImage(ima, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle, GraphicsUnit.Pixel);
				ima.Dispose();
				gtemp.Dispose();

			}

		}
		#endregion

		}
	
}
